﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Billing.DataObjects;

namespace Billing.Win
{
    public partial class CalculatorForm : Billing.WindowsBase.FormBase
    {
        List<CorrectionLine> CorrectionLines = new List<CorrectionLine>();
        List<CorrectionLine> CorrectionLineDetails = new List<CorrectionLine>();

        private Billing.DataObjects.ClientsView ownerClient;
        private Billing.DataObjects.ClientsView newOwnerClient;
        private Billing.DataObjects.AccountsView account;
        public Billing.DataObjects.ClientsView OwnerClient
        {
            get
            {
                return this.ownerClient;
            }
            set
            {
                this.ownerClient = value;
            }
        }
        public Billing.DataObjects.ClientsView NewOwnerClient
        {
            get
            {
                return this.newOwnerClient;
            }
            set
            {
                this.newOwnerClient = value;
            }
        }
        public Billing.DataObjects.AccountsView Account
        {
            get
            {
                return this.account;
            }
            set
            {
                this.account = value;
            }
        }

        public DateTime RemoveDate
        {
            get
            {
                return valRemoveDate.DateTime;
            }
            set
            {
                valRemoveDate.DateTime = value;
            }
        }

        private void SetOwnerClientValues(Billing.DataObjects.ClientsView ownerClient)
        {
            if (ownerClient != null)
            {
                valOwnerClientIdentificationNumber.Value = ownerClient.IdentificationNumber;
                valOwnerClientName.Value = ownerClient.Name;
            }
            else
            {
                valOwnerClientIdentificationNumber.Value = null;
                valOwnerClientName.Value = null;
            }
        }

        private void SetAccountValues(Billing.DataObjects.AccountsView accountsView)
        {

            if (accountsView != null)
            {
                valAccountNumber.Value = accountsView.AccountNumber;

                if (ownerClient == null)
                {
                    using (BillingDataContext context = new BillingDataContext())
                    {
                        ownerClient = context.GetClientViewByID(accountsView.ClientID);
                    }
                    SetOwnerClientValues(ownerClient);
                }
            }
            else
            {
                valAccountNumber.Value = null;
            }
        }

        private void SetRemoveDateValues(DateTime? removeDate)
        {
            if (removeDate != null)
            {
                RemoveDate = removeDate.Value;
            }
        }

        private void SetNewOwnerClientValues(Billing.DataObjects.ClientsView newOwnerClient)
        {
            if (newOwnerClient != null)
            {
                valNewOwnerClientIdentificationNumber.Value = newOwnerClient.IdentificationNumber;
                valNewOwnerClientName.Value = newOwnerClient.Name;
            }
            else
            {
                valNewOwnerClientIdentificationNumber.Value = null;
                valNewOwnerClientName.Value = null;
            }
        }

        private DateTime GetAvailabeMinRemoveDate(
            ClientPhoneActions clientPhoneActions,
            Billing.DataObjects.AccountsView account)
        {
            if (DesignMode) return DateTime.Today;

            DateTime? resultDate = null;
            using (BillingDataContext context = new BillingDataContext())
            {
                context.AccountsGetMinAvailableRemoveDate(account.ClientID, account.AccountNumberID, ref resultDate);
            }
            return resultDate.Value;
        }

        private void DoSelect(object sender, EventArgs e)
        {
            switch (Convert.ToString(((Control)(sender)).Tag))
            {
                case "SelectClient":
                    using (ClientsSelectionForm f = new ClientsSelectionForm())
                    {
                        f.PrepareForSelectDialogStyle();


                        if (f.ShowDialog(this) == DialogResult.OK)
                        {
                            if (f.SelectedObjects.Count > 0)
                            {
                                Billing.DataObjects.ClientsView client = ((Billing.DataObjects.ClientsView)f.SelectedObjects[0].CurrentObject);
                                OwnerClient = client;

                                SetOwnerClientValues(OwnerClient);
                            }
                        }
                    }
                    break;
                case "SelectPhone":
                    using (AccountsSelectionForm f = new AccountsSelectionForm())
                    {
                        f.PrepareForSelectDialogStyle();

                        if (OwnerClient != null)
                        {
                            f.ClientsSearch.ClientID = OwnerClient.ID;
                            f.ClientsSearch.Search();
                        }

                        if (f.ShowDialog(this) == DialogResult.OK)
                        {
                            if (f.SelectedObjects.Count > 0)
                            {
                                Billing.DataObjects.AccountsView accNumber = ((Billing.DataObjects.AccountsView)f.SelectedObjects[0].CurrentObject);
                                Account = accNumber;

                                SetAccountValues(Account);
                            }
                        }
                    }
                    break;
                case "SelectNewClient":
                    using (ClientsSelectionForm f = new ClientsSelectionForm())
                    {
                        f.PrepareForSelectDialogStyle();

                        if (f.ShowDialog(this) == DialogResult.OK)
                        {

                            if (f.SelectedObjects.Count > 0)
                            {
                                Billing.DataObjects.ClientsView client = ((Billing.DataObjects.ClientsView)f.SelectedObjects[0].CurrentObject);
                                NewOwnerClient = client;

                                SetNewOwnerClientValues(NewOwnerClient);
                            }
                        }
                    }
                    break;
            }
        }

        private void valOwnerClientIdentificationNumber_Validating(object sender, CancelEventArgs e)
        {
            if (DesignMode) return;

            int? clientID = null;

            using (BillingDataContext context = new BillingDataContext())
            {
                context.ClientsGetClientByIdentificationNumber(Convert.ToString(valOwnerClientIdentificationNumber.Value), ref clientID);

                if (clientID == -1)
                {
                    DoSelect(this, EventArgs.Empty);
                    return;
                }
                else if (clientID != null)
                {
                    OwnerClient = context.GetClientViewByID(clientID.Value);
                }
                else
                {
                    OwnerClient = null;
                }
            }
            SetOwnerClientValues(OwnerClient);
        }

        private void valNewOwnerClientIdentificationNumber_Validating(object sender, CancelEventArgs e)
        {
            if (DesignMode) return;

            using (BillingDataContext context = new BillingDataContext())
            {
                int? clientID = null;

                context.ClientsGetClientByIdentificationNumber(Convert.ToString(valNewOwnerClientIdentificationNumber.Value), ref clientID);

                if (clientID != null)
                {
                    NewOwnerClient = context.GetClientViewByID(clientID.Value);
                }
                else
                {
                    NewOwnerClient = null;
                }
            }
            SetNewOwnerClientValues(NewOwnerClient);
        }

        private void valOwnerClientIdentificationNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                valOwnerClientName.Select();
            }
        }

        private void valNewOwnerClientIdentificationNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                valNewOwnerClientName.Select();
            }
        }

        private void valAccountNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                valRemoveDate.Select();
            }
        }

        private void valAccountNumber_Validating(object sender, CancelEventArgs e)
        {
            if (DesignMode) return;

            if (OwnerClient == null)
            {
                valAccountNumber.Text = string.Empty;
                return;
            }

            if (string.IsNullOrEmpty(Convert.ToString(valAccountNumber.Value))) return;
            using (BillingDataContext context = new BillingDataContext())
            {
                Billing.DataObjects.AccountNumbersView accountNumber = context.GetAccountNumberByNumber(1, Convert.ToString(valAccountNumber.Value));
                if (accountNumber == null)
                {
                    Account = null;
                }

                Account = context.GetAccountByClient(OwnerClient.ID, accountNumber.ID);
            }
            SetAccountValues(Account);
        }

        public CalculatorForm()
        {
            InitializeComponent();
        }

        private AnalysisSubject analysisSubject;

        private void Analyse()
        {
            try
            {
                Guard.ArgumentNotNull(analysisSubject, "analysisSubject");
                CorrectionLines.Clear();

                switch (analysisSubject.AnalysisType)
                {
                    case AnalysisType.ClientUpdate:
                        AnalyseClientUpdate(analysisSubject);
                        break;
                    case AnalysisType.AccountMove:
                        AnalyseAccountMove(analysisSubject);
                        break;
                    default:
                        throw new BillingApplicationException();
                }
                bsSourceLines.DataSource = CorrectionLines;
                bsDetails.DataSource = CorrectionLineDetails;
                grdSourceLines.BringToFront();
                grdDetails.SendToBack();
                grdSourceLines.DataBind();
                grdDestinatinosLines.DataBind();
            }
            catch (Exception x)
            {
                ShowError(x);
            }
        }

        public void Analyse(AnalysisSubject analysisSubject)
        {
            Guard.ArgumentNotNull(analysisSubject, "analysisSubject");
            this.analysisSubject = analysisSubject;

            grbxOwner.Enabled = false;
            valNewOwnerClientIdentificationNumber.Enabled = false;
            valNewOwnerClientName.Enabled = false;
            btSelectNewOwnerClient.Enabled = false;

            if (analysisSubject.AnalysisType == AnalysisType.AccountMove)
            {
                if (analysisSubject.SourceAccount != null)
                {
                    valOwnerClientIdentificationNumber.Text = analysisSubject.SourceAccount.Account.Client.IdentificationNumber;
                    valOwnerClientName.Text = analysisSubject.SourceAccount.Account.Client.Name;
                    valAccountNumber.Text = analysisSubject.SourceAccount.AccountNumber;
                }

                valRemoveDate.DateTime = analysisSubject.StartDate;

                if (analysisSubject.DestinationClient != null)
                {
                    valNewOwnerClientIdentificationNumber.Text = analysisSubject.DestinationClient.IdentificationNumber;
                    valNewOwnerClientName.Text = analysisSubject.DestinationClient.Name;
                }
            }
            else
            {
                if (analysisSubject.SourceClient != null)
                {
                    valOwnerClientIdentificationNumber.Text = analysisSubject.SourceClient.IdentificationNumber;
                    valOwnerClientName.Text = analysisSubject.SourceClient.Name;
                    valAccountNumber.Text = string.Empty;
                }

                valRemoveDate.DateTime = analysisSubject.StartDate;

                if (analysisSubject.DestinationClient != null)
                {
                    valNewOwnerClientIdentificationNumber.Text = analysisSubject.DestinationClient.IdentificationNumber;
                    valNewOwnerClientName.Text = analysisSubject.DestinationClient.Name;
                }
            }


            Analyse();

            ShowDialog();
        }

        private void AnalyseAccountMove(AnalysisSubject analysisSubject)
        {
            Guard.ArgumentNotNull(analysisSubject, "analysisSubject");
            Guard.ArgumentNotNull(analysisSubject.SourceAccount, "analysisSubject.SourceAccount");
            Guard.ArgumentNotNull(analysisSubject.DestinationClient, "analysisSubject.DestinationClient");

            AccountsView srcAcc = analysisSubject.SourceAccount;
            ClientsView dstCln = analysisSubject.DestinationClient;

            CorrectionLineDetails.Clear();


            using (BillingDataContext context = new BillingDataContext())
            {
                foreach (CorrectionLine cl in context.Calculate(
                    srcAcc.ID,
                    srcAcc.ClientID,
                    dstCln.TaxID,
                    dstCln.ClientTypeID,
                    analysisSubject.StartDate,
                    analysisSubject.EndDate))
                {
                    CorrectionLines.Add(cl);
                }
            }
        }

        private void AnalyseClientUpdate(AnalysisSubject analysisSubject)
        {
            Guard.ArgumentNotNull(analysisSubject, "analysisSubject");
            Guard.ArgumentNotNull(analysisSubject.SourceClient, "analysisSubject.SourceClient");
            Guard.ArgumentNotNull(analysisSubject.DestinationClient, "analysisSubject.DestinationClient");

            ClientsView srcCln = analysisSubject.SourceClient;
            ClientsView dstCln = analysisSubject.DestinationClient;
            splitContainer1.Panel1Collapsed = true;
            this.Width -= grbxSoruceParams.Width;
            this.StartPosition = FormStartPosition.CenterScreen;

            using (BillingDataContext context = new BillingDataContext())
            {
                foreach (CorrectionLine cl in context.Calculate(null,
                                 analysisSubject.SourceClient.ID,
                                dstCln.TaxID,
                                dstCln.ClientTypeID,
                                analysisSubject.StartDate,
                                analysisSubject.EndDate))
                {
                    cl.DestAmount = cl.DestAmount + cl.SourceAmount;
                    if (cl.DestAmount != 0)
                        CorrectionLines.Add(cl);
                }
            }
        }

        private void btAnalyse_Click(object sender, EventArgs e)
        {
            analysisSubject = new AnalysisSubject();

            if (Account == null)
            {
                ShowWarning("გადასატანი ნომერი არ არის მითითებული");
                return;
            }

            if (NewOwnerClient == null)
            {
                ShowWarning("ახალი მფლობელი კლიენტი არ არის მითითებული");
                return;
            }

            analysisSubject.AnalysisType = AnalysisType.AccountMove;
            analysisSubject.SourceAccount = Account;
            analysisSubject.DestinationClient = NewOwnerClient;
            analysisSubject.StartDate = RemoveDate;
            analysisSubject.EndDate = DateTime.Today;
            Analyse();
        }

        private void btClear_Click(object sender, EventArgs e)
        {
            ownerClient = null;
            account = null;
            newOwnerClient = null;
            valOwnerClientIdentificationNumber.Text = string.Empty;
            valOwnerClientName.Text = string.Empty;
            valRemoveDate.DateTime = DateTime.Today;
            valNewOwnerClientIdentificationNumber.Text = string.Empty;
            valNewOwnerClientName.Text = string.Empty;
            valAccountNumber.Text = string.Empty;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void grdSourceLines_DoubleClick(object sender, EventArgs e)
        {
            EnsureDetailsFilled();

            grdSourceLines.SendToBack();
            grdDetails.BringToFront();
        }

        private void EnsureDetailsFilled()
        {
            if (!(CorrectionLineDetails.Count == 0 && CorrectionLines.Count != 0))
            {
                return;
            }

            if (analysisSubject.AnalysisType == AnalysisType.AccountMove)
            {
                AccountsView srcAcc = analysisSubject.SourceAccount;
                ClientsView dstCln = analysisSubject.DestinationClient;

                using (BillingDataContext context = new BillingDataContext())
                {
                    foreach (CorrectionLine cl in context.CalculatorDetails(
                        srcAcc.ID,
                        srcAcc.ClientID,
                        dstCln.TaxID,
                        dstCln.ClientTypeID,
                        analysisSubject.StartDate,
                        analysisSubject.EndDate, null, null))
                    {
                        CorrectionLineDetails.Add(cl);
                    }
                }
            }
            else if (analysisSubject.AnalysisType == AnalysisType.ClientUpdate)
            {
                ClientsView srcCln = analysisSubject.SourceClient;
                ClientsView dstCln = analysisSubject.DestinationClient;

                using (BillingDataContext context = new BillingDataContext())
                {
                    foreach (CorrectionLine cl in context.Calculate(null,
                                     analysisSubject.SourceClient.ID,
                                    dstCln.TaxID,
                                    dstCln.ClientTypeID,
                                    analysisSubject.StartDate,
                                    analysisSubject.EndDate))
                    {
                        CorrectionLines.Add(cl);
                    }
                }
            }

            grdDetails.DataBind();
        }

        private void grdDetails_DoubleClick(object sender, EventArgs e)
        {
            grdSourceLines.BringToFront();
            grdDetails.SendToBack();
        }
    }

    public class AnalysisSubject
    {
        public AnalysisType AnalysisType { get; set; }
        public AccountsView SourceAccount { get; set; }
        public AccountsView DestinationAccount { get; set; }
        public ClientsView SourceClient { get; set; }
        public ClientsView DestinationClient { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }

    public enum AnalysisType
    {
        ClientUpdate,
        AccountMove
    }
}
